home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / x11 / xcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  48.5 KB  |  2,325 lines  |  [TEXT/R*ch]

  1. /* Commands for the X11 interface to Xconq.
  2.    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. #include "conq.h"
  11. #include "xconq.h"
  12. extern void create_orders_window PARAMS ((Side *side, Map *map));
  13.  
  14. char *cmdargstr = NULL;
  15.  
  16. /* The command table is an array of all the commands. */
  17.  
  18. typedef struct cmdtab {
  19.     char fchar;            /* character to match against */
  20.     char *name;            /* Full name of command */
  21.     char *argtypes;        /* String giving info about arguments */
  22.     void (*fn) PARAMS ((Side *side, Map *map));  /* pointer to command's function */
  23.     char *help;                 /* short documentation string */
  24. } CmdTab;
  25.  
  26. static int execute_command_from_table PARAMS ((Side *side, Map *map,
  27.                            CmdTab *cmdtab));
  28. static void execute_named_command PARAMS ((Side *side, Map *map,
  29.                        char *cmdstr));
  30. static int execute_named_command_from_table PARAMS ((Side *side, Map *map,
  31.                             char *cmdstr,
  32.                             CmdTab *cmdtab));
  33. static void describe_commands PARAMS ((int arg, char *key, char *buf));
  34. static void describe_command_table PARAMS ((int arg, char *key, char *buf,
  35.                        CmdTab *cmdtab));
  36. static void aux_add_terrain PARAMS ((Side *side, Map *map, int cancel));
  37. static void aux_add_terrain_2 PARAMS ((Side *side, Map *map, int cancel));
  38. static void do_add_terrain_2 PARAMS ((Side *side, Map *map, int t));
  39. static void aux_build PARAMS ((Side *side, Map *map, int cancel));
  40. static void impl_build PARAMS ((Side *side, Unit *unit, int u2, int n));
  41. static void aux_distance PARAMS ((Side *side, Map *map, int cancel));
  42. static void aux_fire_at PARAMS ((Side *side, Map *map, int cancel));
  43. static void aux_move_look PARAMS ((Side *side, Map *map));
  44. static void aux_move_dir PARAMS ((Side *side, Map *map, Unit *unit));
  45. static void aux_message PARAMS ((Side *side, Map *map, int cancel));
  46. static void aux_move_to PARAMS ((Side *side, Map *map, int cancel));
  47. static void aux_name PARAMS ((Side *side, Map *map, int cancel));
  48. static void aux_others PARAMS ((Side *side, Map *map, int cancel));
  49. static void aux_resign PARAMS ((Side *side, Map *map, int cancel));
  50. static void aux_resign_2 PARAMS ((Side *side, Map *map, int cancel));
  51. static void aux_leave_game PARAMS ((Side *side, Map *map, int cancel));
  52. static void aux_kill_game PARAMS ((Side *side, Map *map, int cancel));
  53. static void aux_resign_b PARAMS ((Side *side, Map *map, int cancel));
  54. static void aux_save_2 PARAMS ((Side *side, Map *map, int cancel));
  55. static void aux_save_1 PARAMS ((Side *side, Map *map, int cancel));
  56. static void aux_save_1_1 PARAMS ((Side *side, Map *map, int cancel));
  57. static void aux_set_formation PARAMS ((Side *side, Map *map, int cancel));
  58. static void save_the_game PARAMS ((Side *side));
  59. static void cmd_error PARAMS ((Side *side, char *fmt, ...));
  60.  
  61. char tmpkey;
  62.  
  63. Map *tmpmap;
  64.  
  65. #define C(c) ((c)-0x40)
  66.  
  67. #undef DEF_CMD
  68. #define DEF_CMD(LETTER,NAME,ARGS,FN,HELP) { LETTER, NAME, ARGS, FN, HELP },
  69.  
  70. /* Define a table of generic Xconq commands. */
  71.  
  72. CmdTab commands[] = {
  73.  
  74. #include "cmd.def"
  75.  
  76.   { 0, NULL, NULL, NULL, NULL }
  77. };
  78.  
  79. /* Define a table of additional X-specific commands. */
  80.  
  81. CmdTab xcommands[] = {
  82.  
  83. #include "xcmd.def"
  84.  
  85.   { 0, NULL, NULL, NULL, NULL }
  86. };
  87.  
  88. static HelpNode *commands_help_node;
  89.  
  90. /* Search in command table and execute function if found, complaining if
  91.    the command is not recognized.  Many commands operate on the "current
  92.    unit", and all uniformly error out if there is no current unit, so put
  93.    that test here. */
  94.  
  95. void
  96. execute_command(side, map)
  97. Side *side;
  98. Map *map;
  99. {
  100.     int found;
  101.  
  102.     side->ui->beepcount = 0;
  103.     cmdargstr = NULL;
  104.     /* Look through the X-specific command table. */
  105.     found = execute_command_from_table(side, map, xcommands);
  106.     if (found)
  107.       return;
  108.     /* Try the generic table. */
  109.     found = execute_command_from_table(side, map, commands);
  110.     if (found)
  111.       return;
  112.     cmd_error(side, "unrecognized command key '%c'", map->inpch);
  113. }
  114.  
  115. static int
  116. execute_command_from_table(side, map, cmdtab)
  117. Side *side;
  118. Map *map;
  119. CmdTab *cmdtab;
  120. {
  121.     CmdTab *cmd;
  122.     char ch = map->inpch;
  123.     void (*fn) PARAMS ((Side *side, Map *map));
  124.     
  125.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  126.     if (ch == cmd->fchar) {
  127.         fn = cmd->fn;
  128.         if (fn == NULL) {
  129.         run_warning("no command function for %s (0x%x)?",
  130.                 cmd->name, ch);
  131.         return TRUE;
  132.         }
  133.         tmpkey = ch;
  134.         (*fn)(side, map);
  135.         /* Whatever might have happened, we *did* find the command. */
  136.         return TRUE;
  137.     }
  138.     }
  139.     return FALSE;
  140. }
  141.  
  142. static void
  143. execute_named_command(side, map, cmdstr)
  144. Side *side;
  145. Map *map;
  146. char *cmdstr;
  147. {
  148.     int found;
  149.     char *cmdname;
  150.  
  151.     parse_long_name_command(cmdstr, &cmdname, &cmdargstr, copy_string(cmdstr)); 
  152.     if (empty_string(cmdname)) {
  153.     notify(side, "No command.");
  154.     }
  155.     /* Look for the command name in the X-specific table. */
  156.     found = execute_named_command_from_table(side, map, cmdname, xcommands);
  157.     if (found)
  158.       return;
  159.     /* Try the generic table. */
  160.     found = execute_named_command_from_table(side, map, cmdname, commands);
  161.     if (found)
  162.       return;
  163.     cmd_error(side, "unrecognized command name \"%s\"", cmdname);
  164. }
  165.  
  166. static int
  167. execute_named_command_from_table(side, map, cmdstr, cmdtab)
  168. Side *side;
  169. Map *map;
  170. char *cmdstr;
  171. CmdTab *cmdtab;
  172. {
  173.     CmdTab *cmd;
  174.     void (*fn) PARAMS ((Side *side, Map *map));
  175.  
  176.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  177.     if (strcmp(cmdstr, cmd->name) == 0) {
  178.         fn = cmd->fn;
  179.         if (fn == NULL) {
  180.         run_warning("no command function for %s?", cmd->name);
  181.         return TRUE;
  182.         }
  183.         tmpkey = cmd->fchar;
  184.         (*fn)(side, map);
  185.         /* Whatever might have happened, we *did* find the command. */
  186.         return TRUE;
  187.     }
  188.     }
  189.     return FALSE;
  190. }
  191.  
  192. /* Describe all the commands. */
  193.  
  194. static void
  195. describe_commands(arg, key, buf)
  196. int arg;
  197. char *key, *buf;
  198. {
  199.     describe_command_table(arg, key, buf, commands);
  200.     strcat(buf, "\n");
  201.     describe_command_table(arg, key, buf, xcommands);
  202. }
  203.  
  204. /* Describe all the commands to be found in a given table. */
  205.  
  206. static void
  207. describe_command_table(arg, key, buf, cmdtab)
  208. int arg;
  209. char *key, *buf;
  210. CmdTab *cmdtab;
  211. {
  212.     CmdTab *cmd;
  213.  
  214.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  215.     if (cmd->fchar != '\0') {
  216.         if (cmd->fchar < ' ' || cmd->fchar > '~') { 
  217.         tprintf(buf, "^%c", (cmd->fchar ^ 0x40));
  218.         } else {
  219.         tprintf(buf, " %c", cmd->fchar);
  220.         }
  221.         strcat(buf, " ");
  222.         strcat(buf, cmd->help);
  223.         strcat(buf, "\n");
  224.     }
  225.     }
  226.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  227.     if (cmd->fchar == '\0') {
  228.         strcat(buf, "\"");
  229.         strcat(buf, cmd->name);
  230.         strcat(buf, "\"");
  231.         strcat(buf, " ");
  232.         strcat(buf, cmd->help);
  233.         strcat(buf, "\n");
  234.     }
  235.     }
  236. }
  237.  
  238. /* Use this macro in any command if it requires a current unit. */
  239.  
  240. #define REQUIRE_UNIT(side, map)  \
  241.   if (!in_play((map)->curunit)) {  \
  242.     (map)->curunit = NULL;  \
  243.     cmd_error((side), "No current unit to command!");  \
  244.     return;  \
  245.   }
  246.  
  247. /* Definitions of all the command functions. */
  248.  
  249. void
  250. do_add_player(side, map)
  251. Side *side;
  252. Map *map;
  253. {
  254.     request_additional_side(cmdargstr);
  255. }
  256.  
  257. void
  258. do_add_terrain(side, map)
  259. Side *side;
  260. Map *map;
  261. {
  262.     int u, t, numtypes, tfirst, possibles[MAXTTYPES];
  263.     Unit *unit = map->curunit;
  264.  
  265.     REQUIRE_UNIT(side, map);
  266.     u = unit->type;
  267.     numtypes = 0;
  268.     for_all_terrain_types(t) {
  269.     if (ut_acp_to_add_terrain(u, t) > 0) {
  270.         possibles[t] = TRUE;
  271.         ++numtypes;
  272.         tfirst = t;
  273.     } else {
  274.         possibles[t] = FALSE;
  275.     }
  276.     }
  277.     if (numtypes == 0) {
  278.     cmd_error(side, "Cannot add terrain using this unit");
  279.     } else if (numtypes == 1) {
  280.     map->argunitid = unit->id;
  281.     do_add_terrain_2(side, map, tfirst);
  282.     } else {
  283.     map->argunitid = unit->id;
  284.     ask_terrain_type(side, map, "Type to add:", possibles, aux_add_terrain);
  285.     }
  286. }
  287.  
  288. static void
  289. aux_add_terrain(side, map, cancel)
  290. Side *side;
  291. Map *map;
  292. int cancel;
  293. {
  294.     int t;
  295.  
  296.     if (cancel)
  297.       return;
  298.     if (map->inpch == '?') {
  299.     notify(side, "Type a key to select terrain type.");
  300.     map->modalhandler = aux_add_terrain;
  301.     return;
  302.     }
  303.     if (grok_terrain_type(side, map, &t)) {
  304.     if (t != NONTTYPE) {
  305.         do_add_terrain_2(side, map, t);
  306.     }
  307.     } else {
  308.     /* beep? */
  309.     }
  310. }
  311.  
  312. /* This is like do_add_terrain, but with a terrain type given. */
  313.  
  314. static void
  315. do_add_terrain_2(side, map, t)
  316. Side *side;
  317. Map *map;
  318. int t;
  319. {
  320.     map->tmpt = t;
  321.     save_cur(side, map);
  322.     ask_position(side, map, "Add/alter where? [click to set]",
  323.          aux_add_terrain_2);
  324. }
  325.  
  326. static void
  327. aux_add_terrain_2(side, map, cancel)
  328. Side *side;
  329. Map *map;
  330. int cancel;
  331. {
  332.     int x, y, dir;
  333.     Unit *unit;
  334.  
  335.     if (cancel)
  336.       return;
  337.     if (map->inpch == '?') {
  338.     notify(side, "Just pick a location!");
  339.     map->modalhandler = aux_add_terrain_2;
  340.     return;
  341.     }
  342.     if (grok_position(side, map, &x, &y)) {
  343.     if (in_area(x, y)) {
  344.         unit = find_unit(map->argunitid);
  345.         if (in_play(unit) && side_controls_unit(side, unit)) {
  346.         switch (t_subtype(map->tmpt)) {
  347.           case cellsubtype:
  348.             prep_alter_cell_action(unit, unit, x, y, map->tmpt);
  349.             break;
  350.           case bordersubtype:
  351.           case connectionsubtype:
  352.             dir = closest_dir(x - unit->x, y - unit->y);
  353.             prep_add_terrain_action(unit, unit, unit->x, unit->y, dir, map->tmpt);
  354.             break;
  355.           case coatingsubtype:
  356.             cmd_error(side, "can't add coatings yet");
  357.             break;
  358.         }
  359.         }
  360.     }
  361.     restore_cur(side, map);
  362.     } else {
  363.     map->modalhandler = aux_add_terrain_2;
  364.     /* beep? */
  365.     }
  366. }
  367.  
  368. void
  369. do_ai_side(side, map)
  370. Side *side;
  371. Map *map;
  372. {
  373.     if (side_has_ai(side)) {
  374.     set_side_ai(side, NULL);
  375.     } else {
  376.     set_side_ai(side, "mplayer");
  377.     }
  378. }
  379.  
  380. void
  381. do_attack(side, map)
  382. Side *side;
  383. Map *map;
  384. {
  385.     notify(side, "can't do generic attacks yet");
  386. }
  387.  
  388. void
  389. do_auto(side, map)
  390. Side *side;
  391. Map *map;
  392. {
  393.     Unit *unit = map->curunit;
  394.     
  395.     REQUIRE_UNIT(side, map);
  396.     if (unit->plan) {
  397.     set_unit_ai_control(side, unit, !unit->plan->aicontrol, FALSE);
  398.     /* a hack */
  399.     unit->plan->waitingfortasks = !unit->plan->aicontrol;
  400.     }
  401. }
  402.  
  403. void
  404. do_build(side, map)
  405. Side *side;
  406. Map *map;
  407. {
  408.     int u, u2, possibles[MAXUTYPES], numtypes, ufirst;
  409.     Unit *unit = map->curunit;
  410.  
  411.     REQUIRE_UNIT(side, map);
  412.     u = unit->type;
  413.     if (!can_build(unit)) {
  414.     cmd_error(side, "%s can't build anything!", unit_handle(side, unit));
  415.     return;
  416.     }
  417.     if (unit->transport != NULL
  418.     && !uu_occ_can_build(unit->transport->type, u)) {
  419.     cmd_error(side, "%s can't build anything while inside another unit!",
  420.           unit_handle(side, unit));
  421.     return;
  422.     }
  423.     numtypes = 0;
  424.     for_all_unit_types(u2) {
  425.     if (uu_acp_to_create(u, u2) > 0 && type_allowed_on_side(u, side)) {
  426.         possibles[u2] = TRUE;
  427.         ++numtypes;
  428.         ufirst = u2;
  429.     } else {
  430.         possibles[u2] = FALSE;
  431.     }
  432.     }
  433.     switch (numtypes) {
  434.       case 0:
  435.     cmd_error(side, "Nothing to build!");
  436.     break;
  437.       case 1:
  438.     /* Only one type to build - do it. */
  439.     impl_build(side, unit, ufirst, map->prefixarg);
  440.     break;
  441.       default:
  442.     /* Player has to choose a type to build. */
  443.     map->argunitid = unit->id;
  444.     ask_unit_type(side, map, "Type to build:", possibles, aux_build);
  445.     break;
  446.     }
  447. }
  448.  
  449. static void
  450. aux_build(side, map, cancel)
  451. Side *side;
  452. Map *map;
  453. int cancel;
  454. {
  455.     int u2;
  456.     Unit *unit;
  457.  
  458.     if (cancel)
  459.       return;
  460.     if (map->inpch == '?') {
  461.     notify(side, "Type a key or click on a unit type to select build.");
  462.     map->modalhandler = aux_build;
  463.     return;
  464.     }
  465.     if (grok_unit_type(side, map, &u2)) {
  466.     if (u2 != NONUTYPE) {
  467.         unit = find_unit(map->argunitid);
  468.         if (in_play(unit) && side_controls_unit(side, unit)) {
  469.         impl_build(side, unit, u2, map->prefixarg);
  470.         }
  471.     }
  472.     } else {
  473.     /* beep? */
  474.     }
  475. }
  476.  
  477. static void
  478. impl_build(side, unit, u2, n)
  479. Side *side;
  480. Unit *unit;
  481. int u2, n;
  482. {
  483.     if (n < 0)
  484.       n = 99;
  485.     notify(side, "%s will build %d %s",
  486.        unit_handle(side, unit), n, u_type_name(u2));
  487.     push_build_task(unit, u2, n);
  488. }
  489.  
  490. void
  491. do_clear_plan(side, map)
  492. Side *side;
  493. Map *map;
  494. {
  495.     Unit *unit = map->curunit;
  496.  
  497.     REQUIRE_UNIT(side, map);
  498.     set_unit_plan_type(side, unit, PLAN_NONE);
  499. }
  500.  
  501. void
  502. do_copying(side, map)
  503. Side *side;
  504. Map *map;
  505. {
  506.     notify(side, "You may copy freely.  See the file COPYING.");
  507. }
  508.  
  509. void
  510. do_delay(side, map)
  511. Side *side;
  512. Map *map;
  513. {
  514.     Unit *unit = map->curunit;
  515.  
  516.     if (unit != NULL) {
  517.     if (unit->plan)
  518.       delay_unit(unit, TRUE);
  519.     } else {
  520.     unit = find_next_awake_mover(side, map->curunit);
  521.     if (unit != map->curunit) {
  522.         set_current_unit(side, map, unit);
  523.     } else {
  524.         cmd_error(side, "No next awake mover found.");
  525.     }
  526.     }
  527. }
  528.  
  529. void
  530. do_detach(side, map)
  531. Side *side;
  532. Map *map;
  533. {
  534.     int rslt;
  535.     Unit *unit = map->curunit;
  536.  
  537.     REQUIRE_UNIT(side, map);
  538.     if (!completed(unit)) {
  539.     cmd_error(side, "%s is incomplete; cannot detach", unit_handle(side, unit));
  540.     return;
  541.     }
  542.     rslt = check_transfer_part_action(unit, unit, unit->hp / 2, NULL);
  543.     if (valid(rslt)) {
  544.     prep_transfer_part_action(unit, unit, unit->hp / 2, NULL);
  545.     } else {
  546.     notify(side, "can't detach for some reason?");
  547.     }
  548. }
  549.  
  550. void
  551. do_detonate(side, map)
  552. Side *side;
  553. Map *map;
  554. {
  555.     int rslt;
  556.     Unit *unit = map->curunit;
  557.  
  558.     REQUIRE_UNIT(side, map);
  559.     rslt = check_detonate_action(unit, unit, unit->x, unit->y, unit->z);
  560.     if (valid(rslt)) {
  561.     prep_detonate_action(unit, unit, unit->x, unit->y, unit->z);
  562.     } else {
  563.     notify(side, "can't detonate for some reason?");
  564.     }
  565. }
  566.  
  567. void
  568. do_dir(side, map)
  569. Side *side;
  570. Map *map;
  571. {
  572.     switch (map->curtool) {
  573.       case looktool:
  574.     if (map->prefixarg < 0)
  575.       map->prefixarg = 1;
  576.     aux_move_look(side, map);
  577.     break;
  578.       case movetool:
  579.       case unitmovetool:
  580.     if (map->curunit != NULL) {
  581.         aux_move_dir(side, map, map->curunit);
  582.     } else {
  583.         cmd_error(side, "No current unit to move!");
  584.     }
  585.     break;
  586.     }
  587. }
  588.  
  589. void
  590. do_dir_multiple(side, map)
  591. Side *side;
  592. Map *map;
  593. {
  594.  
  595.     switch (map->curtool) {
  596.       case looktool:
  597.     if (map->prefixarg < 0)
  598.       map->prefixarg = 10;
  599.     aux_move_look(side, map);
  600.     break;
  601.       case movetool:
  602.       case unitmovetool:
  603.     map->prefixarg = 9999;
  604.     if (map->curunit != NULL) {
  605.         aux_move_dir(side, map, map->curunit);
  606.     } else {
  607.         cmd_error(side, "No current unit to move!");
  608.     }
  609.     break;
  610.     }
  611. }
  612.  
  613. static void
  614. aux_move_look(side, map)
  615. Side *side;
  616. Map *map;
  617. {
  618.     int ndirs, dir, nx, ny;
  619.     Unit *unit;
  620.  
  621.     ndirs = char_to_dir(tmpkey, &dir, NULL, NULL);
  622.     if (ndirs < 1) {
  623.     cmd_error(side, "what direction is that?!?");
  624.     return;
  625.     }
  626.     if (!point_in_dir_n(map->curx, map->cury, dir, map->prefixarg, &nx, &ny)) {
  627.     beep(side);
  628.     return;
  629.     }
  630.     /* (should share with move_look) */
  631.     clear_current(side, map);
  632.     unit = unit_at(nx, ny);
  633.     if (unit != NULL 
  634.     && (side_controls_unit(side, unit) || all_see_all)) {
  635.     set_current_unit(side, map, unit);
  636.     } else {
  637.     set_current_xy(side, map, nx, ny);
  638.     }
  639. }
  640.   
  641. static void
  642. aux_move_dir(side, map, unit)
  643. Side *side;
  644. Map *map;
  645. Unit *unit;
  646. {
  647.     int ndirs, dir, n = map->prefixarg, x, y;
  648.   
  649.     if (!unit->act || !unit->plan) { /* use a more sophisticated test? */
  650.     /* ??? can't act ??? */
  651.     return;
  652.     }
  653.     ndirs = char_to_dir(tmpkey, &dir, NULL, NULL);
  654.     if (ndirs < 1) {
  655.     cmd_error(side, "what direction is that?!?");
  656.     return;
  657.     }
  658.     if (n > 1) {
  659.     DGprintf("Ordering %s to move %d %s\n",
  660.          unit_desig(unit), n, dirnames[dir]);
  661.     set_move_dir_task(unit, dir, n);
  662.     } else {
  663.     if (!point_in_dir(unit->x, unit->y, dir, &x, &y)) {
  664.         return;
  665.     }
  666.     if (!advance_into_cell(side, unit, x, y, unit_at(x, y))) {
  667.         beep(side);
  668.     }
  669.     if (in_play(unit)) {
  670.         map->curx = unit->x;  map->cury = unit->y;
  671.     }
  672. #if 0    /* (this probably should not be here, but check behavior) */
  673.     /* make sure we don't wander too close to the edge... */
  674.     x = map->curx - map->vx;  y = map->cury - map->vy;
  675.     if (y < 3 || y > map->vh - 3) {
  676.         recenter(side, map, map->curx, map->cury);
  677.     }
  678. #endif
  679.     }
  680. }
  681.  
  682. /* Get rid of a unit. */
  683.  
  684. void
  685. do_disband(side, map)
  686. Side *side;
  687. Map *map;
  688. {
  689.     int u;
  690.     Unit *unit = map->curunit;
  691.  
  692.     REQUIRE_UNIT(side, map);
  693.     u = unit->type;
  694. #ifdef DESIGNERS
  695.     /* A designer can take out any unit, no questions asked. */
  696.     if (side->designer) {
  697.     kill_unit(unit, -1);
  698.     return;
  699.     }
  700. #endif /* DESIGNERS */
  701.     if (!completed(unit)) {
  702.     kill_unit(unit, H_UNIT_DISBANDED);
  703.     } else if (u_hp_per_disband(u) > 0) {
  704.     if (prep_disband_action(unit, unit)) {
  705.         notify(side, "%s will go home.", unit_handle(side, unit));
  706.     } else {
  707.         cmd_error(side, "odd failure");
  708.     }
  709.     } else {
  710.     cmd_error(side, "You can't just get rid of the %s!", u_type_name(u));
  711.     }
  712. }
  713.  
  714. void
  715. do_disembark(side, map)
  716. Side *side;
  717. Map *map;
  718. {
  719.     Unit *unit = map->curunit, *transport;
  720.  
  721.     REQUIRE_UNIT(side, map);
  722.     transport = unit->transport;
  723.     if (transport == NULL) {
  724.     cmd_error(side, "Not in a transport");
  725.     return;
  726.     }
  727.     if (!in_play(transport)) {
  728.     cmd_error(side, "Transport is nonsensical?");
  729.     return;
  730.     }
  731.     /* Try moving into the transport's transport, if there is one. */
  732.     if (transport->transport != NULL
  733.         && can_occupy(unit, transport->transport)) {
  734.     prep_enter_action(unit, unit, transport->transport);
  735.     /* (should be able to set up task if can't do action immedly) */
  736.     return;
  737.     }
  738.     /* Try moving into the open in the cell. */
  739.     if (can_occupy_cell(unit, unit->x, unit->y)
  740.     || can_occupy_conn(unit, unit->x, unit->y, unit->z)) {
  741.     prep_move_action(unit, unit, unit->x, unit->y, unit->z);
  742.     /* (should be able to set up task if can't do action immedly) */
  743.     return;
  744.     }
  745.     cmd_error(side, "Can't disembark here!");
  746. }
  747.  
  748. void
  749. do_distance(side, map)
  750. Side *side;
  751. Map *map;
  752. {
  753.     save_cur(side, map);
  754.     ask_position(side, map, "Distance to where? [click to set]", aux_distance);
  755. }
  756.  
  757. static void
  758. aux_distance(side, map, cancel)
  759. Side *side;
  760. Map *map;
  761. int cancel;
  762. {
  763.     int x, y, dist;
  764.  
  765.     if (cancel)
  766.       return;
  767.     if (map->inpch == '?') {
  768.     notify(side, "Not being helpful yet.");
  769.     map->modalhandler = aux_distance;
  770.     return;
  771.     }
  772.     if (grok_position(side, map, &x, &y)) {
  773.     if (in_area(x, y)) {
  774.         dist = distance(map->savedcurx, map->savedcury, x, y);
  775.         notify(side, "The distance is %d cells.", dist);
  776.     }
  777.     restore_cur(side, map);
  778.     } else {
  779.     map->modalhandler = aux_distance;
  780.     /* beep? */
  781.     }
  782. }
  783.  
  784. void
  785. do_distrust(side, map)
  786. Side *side;
  787. Map *map;
  788. {
  789.     Side *side2;
  790.  
  791.     if (cmdargstr) {
  792.     side2 = parse_side_spec(cmdargstr);
  793.     if (side2 != NULL && side2 != side) {
  794.         set_trust(side, side2, 0);
  795.         /* publicize? */
  796.         return;
  797.     } 
  798.     }
  799. }
  800.  
  801. void
  802. do_draw_willingness(side, map)
  803. Side *side;
  804. Map *map;
  805. {
  806.     if (map->prefixarg < 0)
  807.       map->prefixarg = 1;
  808.     set_willing_to_draw(side, (map->prefixarg ? 1 : 0));
  809. }
  810.  
  811. void
  812. do_embark(side, map)
  813. Side *side;
  814. Map *map;
  815. {
  816.     Unit *transport, *occ;
  817.     Unit *unit = map->curunit;
  818.  
  819.     REQUIRE_UNIT(side, map);
  820.     /* look for the first possible transport */
  821.     for_all_stack(unit->x, unit->y, transport) {
  822.     /* make sure its not the transport we're in and we can enter it */
  823.     if (transport != unit->transport &&
  824.         valid(check_enter_action(unit, unit, transport))) {
  825.         prep_enter_action(unit, unit, transport);
  826.         return;
  827.     }
  828.  
  829.     /* check the occupants too */
  830.     for_all_occupants(transport, occ) {
  831.         if (occ != unit->transport &&
  832.         valid(check_enter_action(unit, unit, occ))) {
  833.         prep_enter_action(unit, unit, occ);
  834.         return;
  835.         }
  836.     }
  837.     }
  838.     cmd_error(side, "Nothing for this unit to enter!");
  839. }
  840.  
  841. void
  842. do_end_turn(side, map)
  843. Side *side;
  844. Map *map;
  845. {
  846.     finish_turn(side);
  847. }
  848.  
  849. void
  850. do_fire(side, map)
  851. Side *side;
  852. Map *map;
  853. {
  854.     int sx, sy, x, y;
  855.     Map *map2;
  856.     Unit *other;
  857.     Unit *unit = map->curunit;
  858.  
  859.     REQUIRE_UNIT(side, map);
  860.  
  861.     if (map->frombutton) {
  862.     map->argunitid = unit->id;
  863.     save_cur(side, map);
  864.     ask_position(side, map, "Fire at what unit? [click to set]",
  865.              aux_fire_at);
  866.     return;
  867.     }
  868.  
  869.     map2 = side->ui->mapdown;
  870.     sx = side->ui->sxdown;  sy = side->ui->sydown;
  871.  
  872.     if (x_nearest_cell(side, map2, sx, sy, &x, &y)) {
  873.     if (x != unit->x || y != unit->y) {
  874.         if (unit->act && unit->plan) { /* (should be more sophisticated?) */
  875.         other = unit_at(x, y);
  876.         if (other != NULL) {
  877.             /* There's a unit to fire at. */
  878.             if (other->side == unit->side) {
  879.             cmd_error(side, "You can't fire at one of your own units!");
  880.             } else if (valid(check_fire_at_action(unit, unit, other, -1))) {
  881.             prep_fire_at_action(unit, unit, other, -1);
  882.             }
  883.         } else {
  884.             cmd_error(side, "Nothing there to fire at.");
  885.         }
  886.         }
  887.     }
  888.     }
  889. }
  890.  
  891. static void
  892. aux_fire_at(side, map, cancel)
  893. Side *side;
  894. Map *map;
  895. int cancel;
  896. {
  897.     int x, y;
  898.     Unit *unit, *other;
  899.  
  900.     if (cancel)
  901.       return;
  902.     if (grok_position(side, map, &x, &y)) {
  903.     unit = find_unit(map->argunitid);
  904.     if (x != unit->x || y != unit->y) {
  905.         if (unit->act && unit->plan) { /* (should be more sophisticated?) */
  906.         other = unit_at(x, y);
  907.         if (other != NULL) {
  908.             /* There's a unit to fire at. */
  909.             if (other->side == unit->side) {
  910.             cmd_error(side, "You can't fire at one of your own units!");
  911.             } else if (valid(check_fire_at_action(unit, unit, other, -1))) {
  912.             prep_fire_at_action(unit, unit, other, -1);
  913.             }
  914.         } else {
  915.             cmd_error(side, "Nothing there to fire at");
  916.         }
  917.         }
  918.     }
  919.     restore_cur(side, map);
  920.     } else {
  921.     map->modalhandler = aux_move_to;
  922.     }
  923. }
  924.  
  925. void
  926. do_fire_into(side, map)
  927. Side *side;
  928. Map *map;
  929. {
  930.     int sx, sy, x, y, rslt;
  931.     Map *map2;
  932.     Unit *unit = map->curunit;
  933.  
  934.     REQUIRE_UNIT(side, map);
  935.  
  936.     sx = side->ui->sxdown;
  937.     sy = side->ui->sydown;
  938.     map2 = side->ui->mapdown;
  939.  
  940.     if (x_nearest_cell(side, map2, sx, sy, &x, &y)) {
  941.     if (x != unit->x || y != unit->y) {
  942.         rslt = check_fire_into_action(unit, unit, x, y, 0, -1);
  943.         if (valid(rslt)) {
  944.         prep_fire_into_action(unit, unit, x, y, 0, -1);
  945.         } else {
  946.         cmd_error(side, "%s fire into %d,%d not valid: %s",
  947.               unit_handle(side, unit), x, y,
  948.               action_result_desc(rslt));
  949.         }
  950.     }
  951.     }
  952. }
  953.  
  954. /* Toggle the "follow-action" flag. */
  955.  
  956. void
  957. do_follow_action(side, map)
  958. Side *side;
  959. Map *map;
  960. {
  961.     side->ui->follow_action = !side->ui->follow_action;
  962.     if (side->ui->follow_action) {
  963.     notify(side, "Following the action.");
  964.     } else {
  965.     notify(side, "Not following the action.");
  966.     }
  967. }
  968.  
  969. void
  970. do_force_global_replan(side, map)
  971. Side *side;
  972. Map *map;
  973. {
  974.     force_global_replan(side);
  975. }
  976.  
  977. void
  978. do_give(side, map)
  979. Side *side;
  980. Map *map;
  981. {
  982.     int something = FALSE;
  983.     int n, u, m, r, gift, actual;
  984.     Unit *unit = map->curunit, *main = NULL;
  985.     char buf[BUFSIZE];
  986.  
  987.     if (nummtypes == 0) {
  988.     cmd_error(side, "No materials in this game!");
  989.     return;
  990.     }
  991.     REQUIRE_UNIT(side, map);
  992.     u = unit->type;
  993.     main = unit->transport;
  994.     if (main == NULL) {
  995.     cmd_error(side, "Nothing to give to here!");
  996.     return;
  997.     }
  998.     m = main->type;
  999.     n = (map->prefixarg < 0 ? 1 : map->prefixarg);
  1000.  
  1001.     buf[0] = '\0';
  1002.     for_all_material_types(r) {
  1003.     gift = (n < 0 ? (um_storage_x(m, r) - main->supply[r]) : n);
  1004.     if (gift > 0) {
  1005.         something = TRUE;
  1006.         /* Be stingy if we're low */
  1007.         if (2 * unit->supply[r] < um_storage_x(u, r))
  1008.           gift = max(1, gift/2);
  1009.         actual = transfer_supply(unit, main, r, gift);
  1010.         tprintf(buf, " %d %s", actual, m_type_name(r));
  1011.     }
  1012.     }
  1013.     if (something) {
  1014.     notify(side, "%s gave%s.", unit_handle(side, unit), buf);
  1015.     } else {
  1016.     notify(side, "%s gave nothing.", unit_handle(side, unit));
  1017.     }
  1018. }
  1019.  
  1020. /* Give a unit to another side or make it independent. */
  1021.  
  1022. /* (but giving to indep should be tested, otherwise might kill unit) */
  1023.  
  1024. void
  1025. do_give_unit(side, map)
  1026. Side *side;
  1027. Map *map;
  1028. {
  1029.     int u;
  1030.     Unit *unit = map->curunit;
  1031.  
  1032.     REQUIRE_UNIT(side, map);
  1033.     u = unit->type;
  1034.     if (/* u_change_side(u) || */ side->designer) {
  1035. /*    unit_changes_side(unit, side_n(n), CAPTURE, PRISONER);  */
  1036.     all_see_cell(unit->x, unit->y);
  1037.     } else {
  1038.     cmd_error(side, "You can't just give away %s!",
  1039.           unit_handle(side, unit));
  1040.     }
  1041. }
  1042.  
  1043. void
  1044. do_help(side, map)
  1045. Side *side;
  1046. Map *map;
  1047. {
  1048.     /* Compose the help node for commands and make it be the first one. */
  1049.     if (side->ui->curhelpnode == NULL) {
  1050.     commands_help_node = add_help_node("commands", describe_commands, 0, first_help_node);
  1051.     side->ui->curhelpnode = first_help_node;
  1052.     }
  1053.     popup_help(side);
  1054. }
  1055.  
  1056. /* Send a short (1 line) message to another player.  Some messages are
  1057.    recognized specially, causing various actions. */
  1058.  
  1059. void
  1060. do_message(side, map)
  1061. Side *side;
  1062. Map *map;
  1063. {
  1064.     char prompt[BUFSIZE];
  1065.     Side *side2;
  1066.  
  1067.     side2 = side_n(map->prefixarg);
  1068.     if (side == side2) {
  1069.     cmd_error(side, "You mumble to yourself.");
  1070.     return;
  1071.     }
  1072.     if (side2) {
  1073.     sprintf(prompt, "Say to %s: ", short_side_title(side2));
  1074.     } else {
  1075.     sprintf(prompt, "Broadcast to all: ");
  1076.     }
  1077.     map->argside = side2;
  1078.     ask_string(side, map, prompt, NULL, aux_message);
  1079. }
  1080.  
  1081. static void
  1082. aux_message(side, map, cancel)
  1083. Side *side;
  1084. Map *map;
  1085. int cancel;
  1086. {
  1087.     char *msg;
  1088.     SideMask sidemask;
  1089.  
  1090.     if (cancel)
  1091.       return;
  1092.     if (grok_string(side, map, &msg)) {
  1093.     if (empty_string(msg)) {
  1094.         notify(side, "You keep your mouth shut.");
  1095.         sidemask = NOSIDES;
  1096.     } else if (map->argside == NULL) {
  1097.         notify(side, "You broadcast to everybody.", msg);
  1098.         sidemask = ALLSIDES;
  1099.     } else {
  1100.         notify(side, "You send your message.");
  1101.         sidemask = add_side_to_set(map->argside, NOSIDES);
  1102.     }
  1103.     if (!empty_string(msg) && sidemask != NOSIDES)
  1104.       send_message(side, sidemask, msg);
  1105.     } else {
  1106.     map->modalhandler = aux_message;
  1107.     }
  1108. }
  1109.  
  1110. /* Set unit to move to a given location.  */
  1111.  
  1112. /* The command proper. */
  1113.  
  1114. void
  1115. do_move_to(side, map)
  1116. Side *side;
  1117. Map *map;
  1118. {
  1119.     Unit *unit = map->curunit;
  1120.  
  1121.     REQUIRE_UNIT(side, map);
  1122.     map->argunitid = unit->id;
  1123.     save_cur(side, map);
  1124.     ask_position(side, map, "Move to where? [click to set]",
  1125.          aux_move_to);
  1126. }
  1127.  
  1128. static void
  1129. aux_move_to(side, map, cancel)
  1130. Side *side;
  1131. Map *map;
  1132. int cancel;
  1133. {
  1134.     int x, y;
  1135.     Unit *unit;
  1136.  
  1137.     if (cancel)
  1138.       return;
  1139.     if (grok_position(side, map, &x, &y)) {
  1140.     unit = find_unit(map->argunitid);
  1141. #ifdef DESIGNERS
  1142.     if (side->designer) {
  1143.         designer_teleport(unit, x, y, NULL);
  1144.     } else
  1145. #endif /* DESIGNERS */
  1146.     if (in_play(unit)) {
  1147.         set_move_to_task(unit, x, y);
  1148.     } else {
  1149.         beep(side);
  1150.     }
  1151.     restore_cur(side, map);
  1152.     } else {
  1153.     map->modalhandler = aux_move_to;
  1154.     }
  1155. }
  1156.  
  1157. /* Name/rename the current unit. */
  1158.  
  1159. void
  1160. do_name(side, map)
  1161. Side *side;
  1162. Map *map;
  1163. {
  1164.     char tmpbuf[BUFSIZE];
  1165.     Unit *unit = map->curunit;
  1166.  
  1167.     REQUIRE_UNIT(side, map);
  1168.     map->argunitid = unit->id;
  1169.     sprintf(tmpbuf, "New name for %s:", unit_handle(side, unit));
  1170.     ask_string(side, map, tmpbuf, unit->name, aux_name);
  1171. }
  1172.  
  1173. static void
  1174. aux_name(side, map, cancel)
  1175. Side *side;
  1176. Map *map;
  1177. int cancel;
  1178. {
  1179.     char *name;
  1180.     Unit *unit;
  1181.  
  1182.     if (cancel)
  1183.       return;
  1184.     if (grok_string(side, map, &name)) {
  1185.     unit = find_unit(map->argunitid);
  1186.     if (in_play(unit) && side_controls_unit(side, unit)) {
  1187.         set_unit_name(side, unit, name);
  1188.     } else {
  1189.         cmd_error(side, "Nothing here that could be named!");
  1190.     }
  1191.     } else {
  1192.     map->modalhandler = aux_name;
  1193.     }
  1194. }
  1195.  
  1196. /* This is a command to examine all occupants and suboccupants, in an
  1197.    inorder fashion. */
  1198.  
  1199. /* Should have an option to open up a list window that shows everything
  1200.    all at once. */
  1201.  
  1202. void
  1203. do_occupant(side, map)
  1204. Side *side;
  1205. Map *map;
  1206. {
  1207.     Unit *nextocc;
  1208.     Unit *unit = map->curunit;
  1209.  
  1210.     REQUIRE_UNIT(side, map);
  1211.     nextocc = find_next_occupant(unit);
  1212.     if (nextocc != unit) {
  1213.     set_current_unit(side, map, nextocc);
  1214.     }
  1215. }
  1216.  
  1217. void
  1218. do_other(side, map)
  1219. Side *side;
  1220. Map *map;
  1221. {
  1222.     ask_string(side, map, "Command:", "", aux_others);
  1223. }
  1224.  
  1225. static void
  1226. aux_others(side, map, cancel)
  1227. Side *side;
  1228. Map *map;
  1229. int cancel;
  1230. {
  1231.     char *cmd;
  1232.  
  1233.     if (cancel)
  1234.       return;
  1235.     if (grok_string(side, map, &cmd)) {
  1236.     if (empty_string(cmd)) {
  1237.         notify(side, "No command.");
  1238.     } else if (strcmp(cmd, "?") == 0) {
  1239.         do_help(side, map);
  1240.         /* (should do with special jump routine) */
  1241.         side->ui->curhelpnode = commands_help_node;
  1242.         update_help(side);
  1243.     } else {
  1244.         execute_named_command(side, map, cmd);
  1245.     }
  1246.     } else {
  1247.     map->modalhandler = aux_others;
  1248.     }
  1249. }
  1250.  
  1251. void
  1252. do_print_view(side, map)
  1253. Side *side;
  1254. Map *map;
  1255. {  
  1256.     double conv;
  1257.  
  1258.     if (side->ui->ps_pp == NULL)
  1259.       side->ui->ps_pp = (PrintParameters *) xmalloc(sizeof(PrintParameters));
  1260.  
  1261.     init_ps_print(side->ui->ps_pp);
  1262.  
  1263.     /* convert to cm or in */
  1264.     if (side->ui->ps_pp->cm) {
  1265.     conv = 72 / 2.54;
  1266.     } else {
  1267.     conv = 72;
  1268.     }
  1269.     side->ui->ps_pp->cell_size /= conv;
  1270.     side->ui->ps_pp->cell_grid_width /= conv;
  1271.     side->ui->ps_pp->border_width /= conv;
  1272.     side->ui->ps_pp->connection_width /= conv;
  1273.     side->ui->ps_pp->page_width /= conv;
  1274.     side->ui->ps_pp->page_height /= conv;
  1275.     side->ui->ps_pp->top_margin /= conv;
  1276.     side->ui->ps_pp->bottom_margin /= conv;
  1277.     side->ui->ps_pp->left_margin /= conv;
  1278.     side->ui->ps_pp->right_margin /= conv;
  1279.  
  1280.     popup_print_setup_dialog(side);
  1281. }
  1282.  
  1283. void
  1284. do_produce(side, map)
  1285. Side *side;
  1286. Map *map;
  1287. {
  1288.     notify(side, "can't produce materials by action yet");
  1289. }
  1290.  
  1291. void
  1292. do_quit(side, map)
  1293. Side *side;
  1294. Map *map;
  1295. {
  1296.     if (side->ingame) {
  1297.     if (all_others_willing_to_quit(side)) {
  1298.         /* Everbody else is willing to get out, but confirm us anyway. */
  1299.         ask_bool(side, map, "Do you really want to quit?", FALSE,
  1300.              aux_kill_game);
  1301.     } else {
  1302.         if (1 /* outcome needs resolution */) {
  1303.         /* if not everybody willing to draw, then we have to resign */
  1304.         ask_bool(side, map, "Do you really want to give up?", FALSE,
  1305.              aux_resign);
  1306.         } else {
  1307.         /* Everybody is just participating. */
  1308.         ask_bool(side, map, "Do you want to leave this game?", FALSE,
  1309.              aux_leave_game);
  1310.         }
  1311.     }
  1312.     } else {
  1313.     /* We're already out of the game, not really anything to confirm. */
  1314.     /* (is this common to all interfaces?) */
  1315.     if (all_others_willing_to_quit(side)) {
  1316.         exit_xconq(side);
  1317.     } else {
  1318.         close_display(side);
  1319.         if (num_active_displays() == 0) {
  1320.         exit_xconq(side);
  1321.         }
  1322.     }
  1323.     }
  1324. }
  1325.  
  1326. static void
  1327. aux_resign(side, map, cancel)
  1328. Side *side;
  1329. Map *map;
  1330. int cancel;
  1331. {
  1332.     if (cancel)
  1333.       return;
  1334.     if (grok_bool(side, map)) {
  1335.     if (numsides > 2) {
  1336.         ask_side(side, map, "Who do you want to surrender to?", NULL,
  1337.              aux_resign_2);
  1338.     } else {
  1339.         resign_game(side, NULL);
  1340.     }
  1341.     }
  1342. }
  1343.  
  1344. static void
  1345. aux_resign_2(side, map, cancel)
  1346. Side *side;
  1347. Map *map;
  1348. int cancel;
  1349. {
  1350.     Side *side2;
  1351.  
  1352.     if (cancel)
  1353.       return;
  1354.     grok_side(side, map, &side2);
  1355.     resign_game(side, side2);
  1356. }
  1357.  
  1358. /* Do the act of leaving the game. */
  1359.  
  1360. static void
  1361. aux_leave_game(side, map, cancel)
  1362. Side *side;
  1363. Map *map;
  1364. int cancel;
  1365. {
  1366.     if (cancel)
  1367.       return;
  1368.     if (grok_bool(side, map)) {
  1369.     remove_side_from_game(side);
  1370.     /* Now go back and see what happens if we're not in the game. */ 
  1371.     do_quit(side, NULL);
  1372.     } else {
  1373.     /* nothing to do if we said not to exit */
  1374.     }
  1375. }
  1376.  
  1377. /* (Have an extra confirm for designers not to lose unsaved work?) */
  1378.  
  1379. static void
  1380. aux_kill_game(side, map, cancel)
  1381. Side *side;
  1382. Map *map;
  1383. int cancel;
  1384. {
  1385.     if (cancel)
  1386.       return;
  1387.     if (grok_bool(side, map)) {
  1388.     exit_xconq(side);
  1389.     } else {
  1390.     /* Nothing to do if we said not to exit. */
  1391.     }
  1392. }
  1393.  
  1394. /* Center the screen on the current location. */
  1395.  
  1396. void
  1397. do_recenter(side, map)
  1398. Side *side;
  1399. Map *map;
  1400. {
  1401.     recenter(side, map, map->curx, map->cury);
  1402. }
  1403.  
  1404. /* Redraw everything using the same code as when windows need a redraw. */
  1405.  
  1406. void
  1407. do_refresh(side, map)
  1408. Side *side;
  1409. Map *map;
  1410. {
  1411.     redraw(side);
  1412.     draw_view_in_panner(side, map);
  1413. }
  1414.  
  1415. void
  1416. do_remove_terrain(side, map)
  1417. Side *side;
  1418. Map *map;
  1419. {
  1420.     REQUIRE_UNIT(side, map);
  1421.     notify(side, "can't remove terrain yet");
  1422. }
  1423.  
  1424. void
  1425. do_reserve(side, map)
  1426. Side *side;
  1427. Map *map;
  1428. {
  1429.     REQUIRE_UNIT(side, map);
  1430.     set_unit_reserve(side, map->curunit, TRUE, TRUE /* is this right??? */);
  1431. }
  1432.  
  1433. /* (should reindent) */
  1434. void
  1435. do_resign(side, map)
  1436. Side *side;
  1437. Map *map;
  1438. {
  1439.     if (endofgame) {
  1440.         notify(side, "Game is already over.");
  1441.         beep(side);
  1442.     } else if (!side->ingame) {
  1443.         notify(side, "You are already out of the game.");
  1444.         beep(side);
  1445.     } else {
  1446.         ask_bool(side, map, "You really want to resign?", FALSE, aux_resign_b);
  1447.     }
  1448. }
  1449.  
  1450. /* This is semi-redundant with aux_resign. */
  1451.  
  1452. static void
  1453. aux_resign_b(side, map, cancel)
  1454. Side *side;
  1455. Map *map;
  1456. int cancel;
  1457. {
  1458.     if (cancel)
  1459.       return;
  1460.     if (grok_bool(side, map)) {
  1461.     resign_game(side, NULL);
  1462.     }
  1463. }
  1464.  
  1465. /* Set up a task to resupply the unit. */
  1466.  
  1467. /* (should warn if task is likely to fail) */
  1468.  
  1469. void
  1470. do_return(side, map)
  1471. Side *side;
  1472. Map *map;
  1473. {
  1474.     Unit *unit = map->curunit;
  1475.  
  1476.     REQUIRE_UNIT(side, map);
  1477.     /* (should doublecheck range and error out if no chance) */
  1478.     if (in_play(unit)) {
  1479.     set_resupply_task(unit, NONMTYPE);
  1480.     }
  1481. }
  1482.  
  1483. /* Stuff game state into a file.  By default, it goes into the current
  1484.    directory.  If designing a game, we can specify exactly which parts
  1485.    of the game state are to be written. */
  1486.  
  1487. /* The command proper just sets up different modal handlers, depending on
  1488.    whether we're building (and therefore saving a scenario/fragment), or
  1489.    saving as much game state as possible, for resumption later. */
  1490.  
  1491. void
  1492. do_save(side, map)
  1493. Side *side;
  1494. Map *map;
  1495. {
  1496.     Side *side2;
  1497.  
  1498.     /* First check to see if anybody is in the middle of doing something
  1499.        (like renaming a unit) whose state would be lost. */
  1500.     for_all_sides(side2) {
  1501.     if (side2 != side && side2->busy) {
  1502.         cmd_error(side, "The %s are busy, can't save right now.",
  1503.               plural_form(side2->name));
  1504.     }
  1505.     }
  1506. #ifdef DESIGNERS
  1507.     if (side->designer) {
  1508.     ask_string(side, map, "Types of data to save?", "all",
  1509.            aux_save_1);
  1510.     return;
  1511.     }
  1512. #endif /* DESIGNERS */
  1513.     if (0 /* (should be "savemustquit") */) {
  1514.     ask_bool(side, map, "You really want to save?", FALSE, aux_save_2);
  1515.     } else {
  1516.     save_the_game(side);
  1517.     }
  1518. }
  1519.  
  1520. /* Make a module appropriate to a save file, write the file, and leave. */
  1521.  
  1522. static void
  1523. aux_save_2(side, map, cancel)
  1524. Side *side;
  1525. Map *map;
  1526. int cancel;
  1527. {
  1528.     if (cancel)
  1529.       return;
  1530.     if (grok_bool(side, map)) {
  1531.     save_the_game(side);
  1532.     }
  1533. }
  1534.  
  1535. static void
  1536. save_the_game(side)
  1537. Side *side;
  1538. {
  1539.     char *savename = saved_game_filename();
  1540.  
  1541.     notify_all("Game will be saved to \"%s\" ...", savename);
  1542.     if (write_entire_game_state(savename)) {
  1543.     close_displays();
  1544.     /* this should be conditional? */
  1545.     exit(0);
  1546.     } else {
  1547.     cmd_error(side, "Can't open file \"%s\"!", savename);
  1548.     }
  1549. }
  1550.  
  1551.  
  1552. #ifdef DESIGNERS
  1553.  
  1554. static Module *tmpmodule;
  1555.  
  1556. static void
  1557. aux_save_1_1(side, map, cancel)
  1558. Side *side;
  1559. Map *map;
  1560. int cancel;
  1561. {
  1562.     char *filenamespec;
  1563.  
  1564.     if (cancel)
  1565.       return;
  1566.     if (grok_string(side, map, &filenamespec)) {
  1567.     tmpmodule->filename = filenamespec;
  1568.     notify(side, "File will be written to \"%s\" ...",
  1569.            tmpmodule->filename);
  1570.     if (write_game_module(tmpmodule)) {
  1571.         notify(side, "Done writing to \"%s\".", tmpmodule->filename);
  1572.     } else {
  1573.         cmd_error(side, "Can't open file \"%s\"!", tmpmodule->filename);
  1574.     }
  1575.     } else {
  1576.     map->modalhandler = aux_save_1_1;
  1577.     }
  1578. }
  1579.  
  1580. static void
  1581. aux_save_1(side, map, cancel)
  1582. Side *side;
  1583. Map *map;
  1584. int cancel;
  1585. {
  1586.     int save;
  1587.     char *contentspec;
  1588.  
  1589.     if (cancel)
  1590.       return;
  1591.     if (grok_string(side, map, &contentspec)) {
  1592.     tmpmodule = create_game_module("game-data");
  1593.     /* Use the spec string to decide which pieces to save. */
  1594.     save = FALSE;
  1595.     if (strcmp(contentspec, "all") == 0) {
  1596.         tmpmodule->def_all = TRUE;
  1597.         tmpmodule->compress_layers = TRUE;
  1598.         save = TRUE;
  1599.     } else if (strcmp(contentspec, "world") == 0) {
  1600.         tmpmodule->def_world = TRUE;
  1601.         tmpmodule->def_areas = TRUE;
  1602.         tmpmodule->def_area_terrain = TRUE;
  1603.         tmpmodule->def_area_misc = TRUE;
  1604.         tmpmodule->def_area_weather = TRUE;
  1605.         tmpmodule->def_area_material = TRUE;
  1606.         save = TRUE;
  1607.     } else {
  1608.         cmd_error(side, "Don't understand content spec \"%s\"!",
  1609.               contentspec);
  1610.         return;
  1611.     }
  1612.     if (save) {
  1613.         ask_string(side, map, "Save data to where?", "game-data.g",
  1614.                aux_save_1_1);
  1615.     } else {
  1616.         notify(side, "Nothing requested to be saved.");
  1617.     }
  1618.     } else {
  1619.     map->modalhandler = aux_save_1;
  1620.     }
  1621. }
  1622.  
  1623. #endif /* DESIGNERS */
  1624.  
  1625. void
  1626. do_set_formation(side, map)
  1627. Side *side;
  1628. Map *map;
  1629. {
  1630.     REQUIRE_UNIT(side, map);
  1631.     map->argunitid = map->curunit->id;
  1632.     save_cur(side, map);
  1633.     ask_position(side, map, "Form up on who? [click to set]",
  1634.          aux_set_formation);
  1635. }
  1636.  
  1637. static void
  1638. aux_set_formation(side, map, cancel)
  1639. Side *side;
  1640. Map *map;
  1641. int cancel;
  1642. {
  1643.     int x, y;
  1644.     Unit *unit, *leader;
  1645.  
  1646.     if (cancel)
  1647.       return;
  1648.     if (map->inpch == '?') {
  1649.     notify(side, "Click on a unit that you want to follow.");
  1650.     map->modalhandler = aux_set_formation;
  1651.     return;
  1652.     }
  1653.     if (grok_position(side, map, &x, &y)) {
  1654.     unit = find_unit(map->argunitid);
  1655.     if (in_play(unit) && in_area(x, y)) {
  1656.         leader = unit_at(x, y);
  1657.         if (in_play(leader)
  1658.         && leader != unit
  1659.         && trusted_side(unit->side, leader->side)) {
  1660.         set_formation(unit, leader, leader->x - unit->x, leader->y - unit->y, 1, 1);
  1661.         } else {
  1662.         cmd_error(side, "Nobody here to form on!");
  1663.         }
  1664.     }
  1665.     restore_cur(side, map);
  1666.     } else {
  1667.     map->modalhandler = aux_set_formation;
  1668.     /* beep? */
  1669.     }
  1670. }
  1671.  
  1672. void
  1673. do_set_rate(side, map)
  1674. Side *side;
  1675. Map *map;
  1676. {
  1677.     int slow, fast;
  1678.     char *reststr;
  1679.  
  1680.     if (cmdargstr) {
  1681.     slow = strtol(cmdargstr, &reststr, 10);
  1682.     fast = strtol(reststr, &reststr, 10);
  1683.     set_play_rate(slow, fast);
  1684.     }
  1685. }
  1686.  
  1687. void
  1688. do_sleep(side, map)
  1689. Side *side;
  1690. Map *map;
  1691. {
  1692.     Unit *unit = map->curunit;
  1693.  
  1694.     REQUIRE_UNIT(side, map);
  1695.     set_unit_asleep(side, unit, TRUE, TRUE /* is this right??? */);
  1696. }
  1697.  
  1698. void
  1699. do_standing_orders(side, map)
  1700. Side *side;
  1701. Map *map;
  1702. {
  1703.     int rslt;
  1704.  
  1705.     if (cmdargstr) {
  1706.     rslt = parse_standing_order(side, cmdargstr);
  1707.     if (rslt < 0)
  1708.       cmd_error(side, "Parse error");
  1709.  
  1710.     /* destroy orders window and structures */
  1711.     side->ui->orderlist = NULL;
  1712.     if (side->ui->orders_shell) {
  1713.         XtPopdown(side->ui->orders_shell);
  1714.         XtDestroyWidget(side->ui->orders_shell);
  1715.         side->ui->orders_shell = NULL;
  1716.     }
  1717.  
  1718.     } else
  1719.       cmd_error(side, "No arguments given.");
  1720. }
  1721.  
  1722. void
  1723. do_surrender_to(side, map)
  1724. Side *side;
  1725. Map *map;
  1726. {
  1727.     notify(side, "can't surrender to a side yet");
  1728. }
  1729.  
  1730. void
  1731. do_survey(side, map)
  1732. Side *side;
  1733. Map *map;
  1734. {
  1735.     if (map->curtool == looktool) {
  1736.     map->curtool = movetool;
  1737.     } else if (map->curtool == movetool) {
  1738.     map->curtool = looktool;
  1739.     } else {
  1740.     beep(side);
  1741.     return;
  1742.     }
  1743.     set_tool_cursor(side, map);
  1744.     update_controls(side, map);
  1745. }
  1746.  
  1747. /* Take supplies from transport. */
  1748.  
  1749. void
  1750. do_take(side, map)
  1751. Side *side;
  1752. Map *map;
  1753. {
  1754.     int something = FALSE;
  1755.     int u, u2, m, need, actual, n;
  1756.     Unit *unit = map->curunit, *unit2;
  1757.     char buf[BUFSIZE];
  1758.  
  1759.     if (nummtypes == 0) {
  1760.     cmd_error(side, "No materials in this game!");
  1761.     return;
  1762.     }
  1763.     REQUIRE_UNIT(side, map);
  1764.     u = unit->type;
  1765.     unit2 = unit->transport;
  1766.     if (unit2 == NULL) {
  1767.     cmd_error(side, "Nothing to take from here!");
  1768.     return;
  1769.     }
  1770.     u2 = unit2->type;
  1771.     n = (map->prefixarg < 0 ? 1 : map->prefixarg);
  1772.  
  1773.     buf[0] = '\0';
  1774.     for_all_material_types(m) {
  1775.     need = (n < 0 ? um_storage_x(u, m) - unit->supply[m] : n);
  1776.     if (need > 0) {
  1777.         something = TRUE;
  1778.         /* Be stingy if we're low */
  1779.         if (2 * unit2->supply[m] < um_storage_x(u2, m))
  1780.           need = max(1, need/2);
  1781.         actual = transfer_supply(unit2, unit, m, need);
  1782.         tprintf(buf, " %d %s", actual, m_type_name(m));
  1783.     }
  1784.     }
  1785.     if (something) {
  1786.     notify(side, "%s got%s.", unit_handle(side, unit), buf);
  1787.     } else {
  1788.     notify(side, "%s needed nothing.", unit_handle(side, unit));
  1789.     }
  1790. }
  1791.  
  1792. void
  1793. do_take_unit(side, map)
  1794. Side *side;
  1795. Map *map;
  1796. {
  1797.     REQUIRE_UNIT(side, map);
  1798.     notify(side, "can't take units yet");
  1799. }
  1800.  
  1801. void
  1802. do_trust(side, map)
  1803. Side *side;
  1804. Map *map;
  1805. {
  1806.     Side *side2;
  1807.  
  1808.     if (cmdargstr) {
  1809.     side2 = parse_side_spec(cmdargstr);
  1810.     if (side2 != NULL && side2 != side) {
  1811.         set_trust(side, side2, 1);
  1812.         return;
  1813.     } 
  1814.     }
  1815. }
  1816.  
  1817. /* Command to display the program version. */
  1818.  
  1819. void
  1820. do_version(side, map)
  1821. Side *side;
  1822. Map *map;
  1823. {
  1824.     notify(side, "Xconq version %s", version_string());
  1825.     notify(side, "(c) %s", copyright_string());
  1826. }
  1827.  
  1828. void
  1829. do_wake(side, map)
  1830. Side *side;
  1831. Map *map;
  1832. {
  1833.     /* Do the curunit explicitly, might only be an occupant. */
  1834.     if (in_play(map->curunit)) {
  1835.     wake_unit(map->curunit, FALSE, 0, NULL);
  1836.     draw_map_info(side, map);
  1837.     }
  1838.     /* If an argument was given, apply to all "top-level" units
  1839.        within the radius specified by the argument. */
  1840.     if (map->prefixarg >= 0)
  1841.       wake_area(side, map->curx, map->cury, map->prefixarg, FALSE);
  1842. }
  1843.  
  1844. void
  1845. do_wake_all(side, map)
  1846. Side *side;
  1847. Map *map;
  1848. {
  1849.     int n;
  1850.  
  1851.     n = (map->prefixarg < 0 ? 0 : map->prefixarg);
  1852.     wake_area(side, map->curx, map->cury, n, TRUE);
  1853. }
  1854.  
  1855. void
  1856. do_warranty(side, map)
  1857. Side *side;
  1858. Map *map;
  1859. {
  1860.     notify(side, "There is no warranty.");
  1861. }
  1862.  
  1863. /* X-interface-specific commands. */
  1864.  
  1865. void
  1866. do_x_flash(side, map)
  1867. Side *side;
  1868. Map *map;
  1869. {
  1870.     int i;
  1871.  
  1872.     if (in_area(map->curx, map->cury)) {
  1873.     for (i = 0; i < 2; ++i) {
  1874.         invert_unit_subarea(side, map, map->curx, map->cury);
  1875.         /* (should wait a moment) */
  1876.         invert_unit_subarea(side, map, map->curx, map->cury);
  1877.         draw_row(side, map, map->curx, map->cury, 1, TRUE);
  1878.         if (map->curunit) {
  1879.         draw_current(side, map);
  1880.         }
  1881.         invert_unit_subarea(side, map, map->curx, map->cury);
  1882.         /* (should wait a moment) */
  1883.         invert_unit_subarea(side, map, map->curx, map->cury);
  1884.         draw_row(side, map, map->curx, map->cury, 1, TRUE);
  1885.         if (map->curunit) {
  1886.         draw_current(side, map);
  1887.         }
  1888.     }
  1889.     } else {
  1890.     beep(side);
  1891.     }
  1892. }
  1893.  
  1894. /* Create a new map, of standard size and zoom. */
  1895. /* (should clone last map in list perhaps?) */
  1896.  
  1897. void
  1898. do_x_map(side, map)
  1899. Side *side;
  1900. Map *map;
  1901. {
  1902.     Map *map2;
  1903.  
  1904.     map2 = create_map(side, 5, NULL);
  1905. }
  1906.  
  1907. /* Close a map window permanently. */
  1908.  
  1909. void
  1910. do_x_map_close(side, map)
  1911. Side *side;
  1912. Map *map;
  1913. {
  1914.     /* (should trash map and popdown) */
  1915.     notify(side, "can't close a map yet");
  1916. }
  1917.  
  1918. void
  1919. do_x_reverse_video(side, map)
  1920. Side *side;
  1921. Map *map;
  1922. {
  1923.     if (side->ui->monochrome) {
  1924.     side->ui->bonw = !side->ui->bonw;
  1925.     set_colors(side);
  1926.     reset_color_state(side);
  1927.     redraw(side);
  1928.     } else {
  1929.     cmd_error(side, "Reverse video is only for monochrome!");
  1930.     }
  1931. }
  1932.  
  1933. void
  1934. do_x_unit_closeup(side, map)
  1935. Side *side;
  1936. Map *map;
  1937. {
  1938.     Unit *unit = map->curunit;
  1939.     UnitCloseup *unitcloseup;
  1940.     REQUIRE_UNIT(side, map);
  1941.     
  1942.     unitcloseup = find_unit_closeup(unit, side);
  1943.     if (!unitcloseup)
  1944.       unitcloseup = create_unit_closeup(unit, side, map);
  1945.     draw_unit_closeup(unitcloseup, side);
  1946. }
  1947.  
  1948. void
  1949. do_x_orders_popup(side, map)
  1950. Side *side;
  1951. Map *map;
  1952. {
  1953.   create_orders_window(side, map);
  1954. }
  1955.  
  1956. void
  1957. do_x_side_closeup(side, map)
  1958. Side *side;
  1959. Map *map;
  1960. {
  1961.     Unit *unit = map->curunit;
  1962.     SideCloseup *sidecloseup;
  1963.     REQUIRE_UNIT(side, map);
  1964.     
  1965.     sidecloseup = find_side_closeup(unit->side, side);
  1966.     if (!sidecloseup)
  1967.       sidecloseup = create_side_closeup(unit->side, side, map);
  1968.     draw_side_closeup(sidecloseup, side);
  1969. }
  1970.  
  1971. /* Create a new world map (a regular map zoomed to display the whole
  1972.    world at once). */
  1973.  
  1974. void
  1975. do_x_world_map(side, map)
  1976. Side *side;
  1977. Map *map;
  1978. {
  1979.     Map *wmap;
  1980.  
  1981.     wmap = create_map(side, -1, NULL);
  1982. }
  1983.  
  1984. void
  1985. do_x_zoom_in(side, map)
  1986. Side *side;
  1987. Map *map;
  1988. {
  1989.     zoom_in_out(side, map, ZOOM_IN);
  1990. }
  1991.  
  1992. void
  1993. do_x_zoom_out(side, map)
  1994. Side *side;
  1995. Map *map;
  1996. {
  1997.     zoom_in_out(side, map, ZOOM_OUT);
  1998. }
  1999.  
  2000. #ifdef DESIGNERS
  2001.  
  2002. static void aux_design PARAMS ((Side *side, Map *map, int cancel));
  2003. static void aux_set_terrain_type PARAMS ((Side *side, Map *map, int cancel));
  2004. static void aux_set_unit_type PARAMS ((Side *side, Map *map, int cancel));
  2005. static int check_designer_status PARAMS ((Side *side, char *str));
  2006.  
  2007. int designed_on = FALSE;
  2008.  
  2009. void enable_in_unit_type_list PARAMS ((Side *side, Map *map, int u, int flag));
  2010.  
  2011. static void really_do_design PARAMS ((Side *side));
  2012.  
  2013. void
  2014. do_design(side, map)
  2015. Side *side;
  2016. Map *map;
  2017. {
  2018.     int u;
  2019.     Map *map2;
  2020.  
  2021.     if (!side->designer) {
  2022.     if (!designed_on) {
  2023.         ask_bool(side, map, "Do you really want to start designing?",
  2024.              FALSE, aux_design);
  2025.     } else {
  2026.         really_do_design(side);
  2027.     }
  2028.     } else {
  2029.     become_nondesigner(side);
  2030.     for_all_maps(side, map2) {
  2031.         map2->seeall = (all_see_all || side->may_set_see_all);
  2032.         update_controls(side, map2);
  2033.         for_all_unit_types(u) {
  2034.         enable_in_unit_type_list(side, map2, u, FALSE);
  2035.         }
  2036.     }
  2037.     popdown_design(side);
  2038.     }
  2039. }
  2040.  
  2041. static void
  2042. aux_design(side, map, cancel)
  2043. Side *side;
  2044. Map *map;
  2045. int cancel;
  2046. {
  2047.     if (cancel)
  2048.       return;
  2049.     if (grok_bool(side, map)) {
  2050.     really_do_design(side);
  2051.     } else {
  2052.     /* nothing to do if we said not to design */
  2053.     }
  2054. }
  2055.  
  2056. static void
  2057. really_do_design(side)
  2058. Side *side;
  2059. {
  2060.     int u;
  2061.     Map *map2;
  2062.  
  2063.     become_designer(side);
  2064.     for_all_maps(side, map2) {
  2065.     map2->seeall = (all_see_all || side->may_set_see_all);
  2066.     update_controls(side, map2);
  2067.     for_all_unit_types(u) {
  2068.         enable_in_unit_type_list(side, map2, u, TRUE);
  2069.     }
  2070.     }
  2071.     popup_design(side);
  2072. }
  2073.  
  2074. void
  2075. do_gdl(side, map)
  2076. Side *side;
  2077. Map *map;
  2078. {
  2079.     if (cmdargstr)
  2080.       interp_form(NULL, read_form_from_string(cmdargstr, NULL, NULL));
  2081.     /* (should broadcast to all?) */
  2082. }
  2083.  
  2084. static int
  2085. check_designer_status(side, str)
  2086. Side *side;
  2087. char *str;
  2088. {
  2089.     if (side->designer) {
  2090.     return TRUE;
  2091.     } else {
  2092.     cmd_error(side, "You're not a designer, can't %s!", str);
  2093.     return FALSE;
  2094.     }
  2095. }
  2096.  
  2097. void
  2098. do_x_set_terrain_type(side, map)
  2099. Side *side;
  2100. Map *map;
  2101. {
  2102.     int numtypes;
  2103.  
  2104.     if (!check_designer_status(side, "set terr paint type"))
  2105.       return;
  2106.     numtypes = ask_terrain_type(side, map, "Type to paint: ", NULL,
  2107.                 aux_set_terrain_type);
  2108.     switch (numtypes) {
  2109.       case 0:
  2110.     beep(side);
  2111.     break;
  2112.       case 1:
  2113.     side->ui->curttype = map->tvec[0];
  2114.     if (map->prefixarg >= 0)
  2115.       side->ui->curbrushradius = map->prefixarg;
  2116.     notify(side, "will now be painting %d-radius %s.",
  2117.            side->ui->curbrushradius, t_type_name(side->ui->curttype));
  2118.     break;
  2119.       default:
  2120.     break;
  2121.     }
  2122. }
  2123.  
  2124. static void
  2125. aux_set_terrain_type(side, map, cancel)
  2126. Side *side;
  2127. Map *map;
  2128. int cancel;
  2129. {
  2130.     int t2;
  2131.  
  2132.     if (cancel)
  2133.       return;
  2134.     if (map->inpch == '?') {
  2135.     notify(side, "Not being helpful yet.");
  2136.     map->modalhandler = aux_set_terrain_type;
  2137.     return;
  2138.     }
  2139.     if (grok_terrain_type(side, map, &t2)) {
  2140.     if (t2 != NONUTYPE) {
  2141.         side->ui->curttype = t2;
  2142.         if (map->prefixarg >= 0)
  2143.           side->ui->curbrushradius = map->prefixarg;
  2144.         notify(side, "will now be painting %d-radius %s.",
  2145.            side->ui->curbrushradius, t_type_name(side->ui->curttype));
  2146.     }
  2147.     } else {
  2148.     /* beep? */
  2149.     }
  2150. }
  2151.  
  2152. /* Command to paint terrain. */
  2153.  
  2154. void
  2155. do_x_paint_terrain(side, map)
  2156. Side *side;
  2157. Map *map;
  2158. {
  2159.     if (!check_designer_status(side, "paint terrain"))
  2160.       return;
  2161.     paint_cell(side, map->curx, map->cury,
  2162.            side->ui->curbrushradius, side->ui->curttype);
  2163. }
  2164.  
  2165. /* Command to set the current unit type to create. */
  2166.  
  2167. void
  2168. do_x_set_unit_type(side, map)
  2169. Side *side;
  2170. Map *map;
  2171. {
  2172.     int numtypes;
  2173.  
  2174.     if (!check_designer_status(side, "set unit type"))
  2175.       return;
  2176.     numtypes = ask_unit_type(side, map, "Type to create: ", NULL,
  2177.                  aux_set_unit_type);
  2178.     switch (numtypes) {
  2179.       case 0:
  2180.     beep(side);
  2181.     break;
  2182.       case 1:
  2183.     side->ui->curutype = map->uvec[0];
  2184.     if (map->prefixarg >= 0)
  2185.       side->ui->cursidenumber = map->prefixarg;
  2186.     notify(side, "will now be creating %s %s units",
  2187.            side_adjective(side_n(side->ui->curusidenumber)),
  2188.            u_type_name(side->ui->curutype));
  2189.     break;
  2190.       default:
  2191.     break;
  2192.     }
  2193. }
  2194.  
  2195. static void
  2196. aux_set_unit_type(side, map, cancel)
  2197. Side *side;
  2198. Map *map;
  2199. int cancel;
  2200. {
  2201.     int u2;
  2202.  
  2203.     if (cancel)
  2204.       return;
  2205.     if (map->inpch == '?') {
  2206.     notify(side, "Not being helpful yet.");
  2207.     map->modalhandler = aux_set_unit_type;
  2208.     return;
  2209.     }
  2210.     if (grok_unit_type(side, map, &u2)) {
  2211.     if (u2 != NONUTYPE) {
  2212.         side->ui->curutype = u2;
  2213.         if (map->prefixarg >= 0)
  2214.           side->ui->cursidenumber = map->prefixarg;
  2215.         notify(side, "will now be creating side %d %s units",
  2216.            side->ui->cursidenumber, u_type_name(side->ui->curutype));
  2217.     }
  2218.     } else {
  2219.     /* beep? */
  2220.     }
  2221. }
  2222.  
  2223. /* Command to create and place a unit. */
  2224.  
  2225. void
  2226. do_x_add_unit(side, map)
  2227. Side *side;
  2228. Map *map;
  2229. {
  2230.     Unit *unit;
  2231.  
  2232.     if (!check_designer_status(side, "create units"))
  2233.       return;
  2234.     unit = designer_create_unit(side,
  2235.                 side->ui->curutype, side->ui->cursidenumber,
  2236.                 map->curx, map->cury);
  2237.     if (unit != NULL) {
  2238.     set_current_unit(side, map, unit);
  2239.     } else {
  2240.     cmd_error(side, "Unit creation failed!");
  2241.     }
  2242. }
  2243.  
  2244. #endif /* DESIGNERS */
  2245.  
  2246. #ifdef DEBUGGING
  2247.  
  2248. /* Debugging-related commands. */
  2249.  
  2250. /* General debugging toggles. */
  2251.  
  2252. void
  2253. do_debug(side, map)
  2254. Side *side;
  2255. Map *map;
  2256. {
  2257. #ifndef Debug
  2258.     Debug = !Debug;
  2259. #endif
  2260. }
  2261.  
  2262. void
  2263. do_debugg(side, map)
  2264. Side *side;
  2265. Map *map;
  2266. {
  2267. #ifndef DebugG
  2268.     DebugG = !DebugG;
  2269. #endif
  2270.     XSynchronize(side->ui->dpy, DebugG);
  2271. }
  2272.  
  2273. void
  2274. do_debugm(side, map)
  2275. Side *side;
  2276. Map *map;
  2277. {
  2278. #ifndef DebugM
  2279.     DebugM = !DebugM;
  2280. #endif
  2281. }
  2282.  
  2283. /* Pretend to be a monochrome screen - use for comparing color
  2284.    and b/w appearance of screens. */
  2285.  
  2286. void
  2287. do_x_fake_mono(side, map)
  2288. Side *side;
  2289. Map *map;
  2290. {
  2291.     side->ui->monochrome = !side->ui->monochrome;
  2292.     side->ui->bonw = BLACKONWHITE;
  2293.     set_colors(side);
  2294.     reset_color_state(side);
  2295.     redraw(side);
  2296. }
  2297.  
  2298. #endif /* DEBUGGING */
  2299.  
  2300. /* Generic command error feedback. */
  2301.  
  2302. static void
  2303. #ifdef ANSI_PROTOTYPES
  2304. cmd_error(Side *side, char *fmt, ...)
  2305. #else
  2306. cmd_error(side, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  2307. Side *side;
  2308. char *fmt;
  2309. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  2310. #endif
  2311. {
  2312. #ifdef ANSI_PROTOTYPES
  2313.     va_list ap;
  2314.  
  2315.     va_start(ap, fmt);
  2316.     vnotify(side, fmt, ap);
  2317.     va_end(ap);
  2318. #else
  2319.     notify(side, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  2320. #endif
  2321.     /* Only beep once, even if a command generates multiple error messages. */
  2322.     if (side->ui->beepcount++ < 1)
  2323.       beep(side);
  2324. }
  2325.